home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 8 / FM Towns Free Software Collection 8.iso / data / happyps2 / 3yama.pas < prev    next >
Pascal/Delphi Source File  |  1994-06-01  |  5KB  |  110 lines

  1. {*********************************************************************
  2.  *  *** 三山くずし ***                                               *
  3.  *                                                                   *
  4.  *     3つの山にいくつかの石がある。あなたとコンピュータが交互に     *
  5.  *     どこかの山からいくつかの石を取っていく。最後の石を取った      *
  6.  *     方が勝ち。このゲーム、先手必勝です。あなたは先手です。    *
  7.  *     でも勝つ規則を知らなければ絶対に勝てないし、規則を知って      *
  8.  *     いたら馬鹿らしくてゲームにならないでしょう。                  *
  9.  *                                                                   *
  10.  *        HAPPyのサンプルプログラム                                  *
  11.  *          (作者  浅野比富美 Public Domain Software)                *
  12.  *********************************************************************}
  13.  
  14. program Mitsuyama(input,output) ;
  15.  
  16.   const  StoneNum = 50    ;             { 3つの山の最初の石の数 }
  17.          YOU      = true  ;             { あなたの番            }
  18.          COM      = false ;             { コンピュータの番      }
  19.  
  20.   type   YamaRange = 1..3 ;             { 山番号の範囲 }
  21.  
  22.   var    YOUorCOM : Boolean ;                         { YOU または COM  }
  23.          yama     : array[YamaRange] of 0..StoneNum ; { 3つの山         }
  24.          i        : YamaRange ;                       { for文の制御変数 }
  25.  
  26. {**********************************}
  27. {* n1,n2の排他的論理和を求める関数*}
  28. {**********************************}
  29.   function nimsum(n1,n2:integer) : integer ;
  30.     var s,m,k,l : integer ;
  31.   begin
  32.     s := 0 ;
  33.     if n1>n2 then m:=n1                 { n1,n2の大きい方をmに }
  34.              else m:=n2 ;
  35.     k:=1 ;
  36.     while m>k do k:=k*2 ;               { mより大きい2のべき乗をk }
  37.     repeat
  38.       l:=0 ;                                          { 0 0 -> 0 }
  39.       if n1>=k then begin n1:=n1-k ; l:=k    end ;    { 0 1 -> 1 }
  40.       if n2>=k then begin n2:=n2-k ; l:=k-l  end ;    { 1 0 -> 1 }
  41.       s:=s+l ;                                        { 1 1 -> 0 }
  42.       k:=k div 2
  43.     until n1=n2 ;                       { n1=n2ならば それ以降の和は0だから }
  44.     nimsum := s
  45.   end {nimsum} ;
  46.  
  47. {**********************************}
  48. {*    3つの山の石数を出力する     *}
  49. {**********************************}
  50.   procedure printstone ;
  51.     var i : YamaRange  ;
  52.   begin
  53.     writeln ;
  54.     for i:=1 to 3 do write(i:4,'山=',yama[i]:3)
  55.   end {printstone};
  56.  
  57. {*************************************}
  58. {*    石を取る(残り石がある時は真)   *}
  59. {*************************************}
  60.   function getstone(YOUorCOM : Boolean) : Boolean ;
  61.     var ok      : Boolean ;
  62.         yamaNo  : integer ;             { 取る山の番号 }
  63.         HowMany : integer ;             { 取る石の数   }
  64.         N       : integer ;             { 3つの山の排他的論理和 }
  65.   begin
  66.     if YOUorCOM = YOU then              { あなたが石を取る番 }
  67.     begin
  68.       ok := false ;                     { どの山からいくつ取るか入力する }
  69.       repeat
  70.         printstone ;
  71.         write('  どこから いくつ ? ') ;
  72.         readln(yamaNo,HowMany) ;
  73.         ok := (1<=yamaNo) and (yamaNo<=3)  ;
  74.         if ok then ok := (1<=HowMany) and (HowMany<=yama[yamaNo])
  75.       until ok ;
  76.     end
  77.     else {YOUorCOM = COM}               { コンピュータが石を取る番 }
  78.     begin
  79.       N := nimsum(nimsum(yama[1],yama[2]),yama[3]) ;
  80.       if  N = 0 then                   { 相手が必勝パターンの時    }
  81.       begin                            { 最も多い山から1個だけ取る }
  82.         if      (yama[1] > yama[2]) and (yama[1] > yama[3]) then yamaNo:=1
  83.         else if (yama[2] > yama[3])                         then yamaNo:=2
  84.         else                                                     yamaNo:=3 ;
  85.         HowMany := 1
  86.       end
  87.       else                              { コンピュータが必勝パターンの時 }
  88.       begin
  89.         yamaNo := 1 ;                   { 必勝パターンとなる山と数を見つける }
  90.         while nimsum(N,yama[yamaNo]) >= yama[yamaNo] do yamaNo:=yamaNo+1 ;
  91.         HowMany := yama[yamaNo]-nimsum(N,yama[yamaNo])
  92.       end ;
  93.       printstone ;
  94.       writeln('  コンピュータは',yamaNo:1,'山から',HowMany:3,'個取ります')
  95.     end ;
  96.     yama[yamaNo] := yama[yamaNo] - HowMany ;   { 石を取る }
  97.     getstone := (yama[1]+yama[2]+yama[3] <> 0) { 石が全部なくなったら  偽 }
  98.   end {getstone} ;
  99.  
  100. {**********************************}
  101. {*      メイン処理                *}
  102. {**********************************}
  103. begin
  104.   for i:=1 to 3 do yama[i] := StoneNum ;
  105.   YOUorCOM := YOU ;                     { あなたが先攻です }
  106.   while getstone(YOUorCOM) do YOUorCOM := not YOUorCOM ;
  107.   if YOUorCOM  = YOU then writeln('あなたの勝ち')
  108.                      else writeln('コンピュータの勝ち')
  109. end.
  110.